package com.sugon.controller.device;

import cn.afterturn.easypoi.entity.vo.TemplateExcelConstants;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.DataFilter;
import com.sugon.annotation.LimitSubmit;
import com.sugon.annotation.NonBusinessParamValid;
import com.sugon.dao.DevRepairRecordDao;
import com.sugon.entity.*;
import com.sugon.entity.vo.TicketLiveImageGroup;
import com.sugon.modules.alarm.service.AlarmCodeBaseService;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.device.consts.DeviceTicketSource;
import com.sugon.modules.device.model.vo.PerfectDevRepairRecordParamVO;
import com.sugon.modules.device.service.IDeviceRepairManager;
import com.sugon.service.*;
import com.sugon.utils.PageUtils;
import com.sugon.utils.Query;
import com.sugon.utils.R;
import com.sugon.utils.ShiroUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 维修记录Controller
 *
 * @author YuXD
 * @date 2023-05-20
 */
@Slf4j
@Controller
@RequestMapping("devRepairRecord")
public class DevRepairRecordController {

    @Resource
    private DevMaintenRepairService devMaintenRepairService;
    @Resource
    private DevRepairRecordService repairRecordService;
    @Resource
    private DevRepairRecordDao devRepairRecordDao;
    @Resource
    private IDeviceRepairManager deviceRepairManager;
    @Resource
    private DeviceInfoService deviceService;
    @Resource
    private AlarmCategoryService alarmCategoryService;
    @Resource
    private AlarmCodeBaseService alarmCodeBaseService;
    @Resource
    private DevFaultPreventMeasureService devFaultPreventMeasureService;
    @Resource
    private TicketLiveImageService ticketLiveImageService;
    @Resource
    private DevMaintenThirdpartyCbService thirdpartyCbService;
    @Resource
    private SysConfigService configService;
    @Resource
    private SparePartConsumRecordService sparePartConsumRecordService;

    /**
     * thinworks平台回调
     *
     * @param callbackParam
     * @return
     */
    @NonBusinessParamValid
    @RequestMapping("/callback")
    @ResponseBody
    public R callback(@Validated @RequestBody DevMaintenThirdpartyCbEntity callbackParam, BindingResult bindingResult) {
        log.info("监听到thinworks平台回调，回调内容：" + JSON.toJSONString(callbackParam));
        /*
            1、是数据的完整性：产线码、设备码
            2、确定产线码和设备码的有效性
            3、确定回调数据属于维修的哪个阶段：上报、开始维修、结束维修 ，以及是否重复
         */
        // 确定产线码和设备码的有效性
        /*
            设备分为机加设备+铸造设备
            机加设备：产线 + 设备码 -> 设备唯一码，根据设备唯一码匹配设备
            铸造设备：ERMS中的设备编码，CQA-XXXXX -> 根据设备编码匹配设备
         */
        // 优先根据第三方回调传递的业务ID查询是否有已知记录
        String devId = null, devType = null;
        String busId = callbackParam.getBusId();
        if (StrUtil.isNotEmpty(busId)) {
            List<DevMaintenThirdpartyCbEntity> cbRecordList = thirdpartyCbService.queryByBusId(busId);
            if (CollectionUtil.isNotEmpty(cbRecordList)) {
                devId = cbRecordList.get(0).getDevId();
                // 相同业务单号的维修分类保持一致：维修分类
                callbackParam.setCategory(cbRecordList.get(0).getCategory());
                callbackParam.setErmsBusId(cbRecordList.get(0).getErmsBusId());
            }
        }
        // 如果没有匹配的回调记录，则根据设备编码(一般为ERMS系统的设备编码)进行匹配
        if (StrUtil.isEmpty(devId)) {
            // 优先识别下铸造设备
            String machineCode = callbackParam.getMachineCode();
            if (StrUtil.isNotEmpty(machineCode)) {
                DeviceInfoEntity device = deviceService.getInfoByDevCode(machineCode);
                if (device != null) {
                    devId = device.getId();
                    devType = device.getDevTypeS();
                }
            }
        }
        // 继续使用产线代码+设备编码 -> 设备底层唯一码进行匹配
        if (StrUtil.isEmpty(devId)) {
            DeviceInfoEntity device = deviceService.queryByDevLastCode(callbackParam.getLineCode(), callbackParam.getMachineCode());
            if (device != null) {
                devId = device.getId();
                devType = device.getDevTypeS();
            }
        }
        // 到此为止，如果仍未匹配到，说明是无效的记录，不允许走后续逻辑
        if (!StrUtil.isAllNotEmpty(devId)) {
            return R.error("根据产线码和设备码无法识别具体设备，请确认！");
        }
        callbackParam.setDevId(devId);
        callbackParam.setDeviceType(devType);
        callbackParam.setContent(JSON.toJSONString(callbackParam));
        return thirdpartyCbService.addThirdPartyCbData(callbackParam) ? R.ok() : R.error("回调失败");
    }

    @AutoLog(value = "导出维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequiresPermissions("devmaintenwork:export")
    @RequestMapping("/export")
    @ResponseBody
    public void export(@RequestParam Map<String, Object> params, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) {
        // 设置导出EXCEL模板名称
        modelMap.put(TemplateExcelConstants.FILE_NAME, "设备维修记录导出_" + DateUtil.format(DateUtil.date(), "yyyyMMdd"));
        // 设置导出模板参数
        TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "deviceRepairTicketTemplate.xlsx");
        templateExportParams.setColForEach(true);
        modelMap.put(TemplateExcelConstants.PARAMS, templateExportParams);
        // 获取设备维护计划预览模板数据
        Map<String, Object> mapData = MapUtil.newHashMap(1);
        // 获取预防性维护计划数据
        // 维修开始时间
        String beginTime = MapUtil.getStr(params, "beginTime");
        if (StrUtil.isNotEmpty(beginTime)) {
            params.put("beginTime", DateUtil.formatDateTime(DateUtil.beginOfDay(DateUtil.parseDate(beginTime))));
        }
        // 维修终止时间
        String endTime = MapUtil.getStr(params, "endTime");
        if (StrUtil.isNotEmpty(endTime)) {
            params.put("endTime", DateUtil.formatDateTime(DateUtil.endOfDay(DateUtil.parseDate(endTime))));
        }
        params.put("delFlag", 1);
        mapData.put("list", repairRecordService.prepareExportData(params));
        modelMap.put(TemplateExcelConstants.MAP_DATA, mapData);
        PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
    }

    /**
     * 查看列表
     */
    @DataFilter(deptAlias = "DMW.WORKSHOP_ID", userAlias = {"DMW.REPAIR_USER", "DMW.UPLOAD_ID"})
    @RequestMapping("/list")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        // 维修开始时间
        String beginTime = MapUtil.getStr(params, "beginTime");
        if (StrUtil.isNotEmpty(beginTime)) {
            params.put("beginTime", DateUtil.formatDateTime(DateUtil.beginOfDay(DateUtil.parseDate(beginTime))));
        }
        // 维修终止时间
        String endTime = MapUtil.getStr(params, "endTime");
        if (StrUtil.isNotEmpty(endTime)) {
            params.put("endTime", DateUtil.formatDateTime(DateUtil.endOfDay(DateUtil.parseDate(endTime))));
        }
        // 报警分类ID
        String faultCategoryId = MapUtil.getStr(params, "faultCategoryId");
        if (StrUtil.isNotEmpty(faultCategoryId)) {
            AlarmCategoryEntity alarmCategory = alarmCategoryService.queryObject(faultCategoryId);
            if (alarmCategory != null) {
                params.put("alarmCode", alarmCategory.getCode());
            }
        }
        //查询列表数据
        Query query = new Query(params);
        List<DevRepairRecordEntity> devMaintenRepairList = repairRecordService.queryList(query);
        int total = repairRecordService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(devMaintenRepairList, total, query.getLimit(), query.getPage());
        // 设置总时长字段
        List<DevRepairRecordEntity> devRepairRecordList = devRepairRecordDao.queryAll(query);
        if (CollectionUtil.isNotEmpty(devRepairRecordList)) {
            pageUtil.put("total", devRepairRecordList.stream().filter(repairRecord -> repairRecord.getDuration() != null).mapToInt(DevRepairRecordEntity::getDuration).sum());
        } else {
            pageUtil.put("total", 0);
        }
        return R.ok().put("page", pageUtil);
    }

    /**
     * 查看信息
     */
    @RequestMapping("/info/{id}")
    @ResponseBody
    public R info(@PathVariable("id") String id) {
        DevRepairRecordEntity repairRecord = repairRecordService.queryObject(id);
        if (repairRecord == null) {
            return R.error("设备维修记录不存在，请确认！");
        }
        // 设置设备报警分类：大类、种类、小类的ID
        if (StrUtil.isNotEmpty(repairRecord.getFaultCategoryId())) {
            List<String> alarmCatetoryIdList = alarmCategoryService.listBMS(repairRecord.getFaultCategoryId());
            if (CollectionUtil.isNotEmpty(alarmCatetoryIdList)) {
                for (int i = 0; i < alarmCatetoryIdList.size(); i++) {
                    if (i == 0) {
                        repairRecord.setVrtId(alarmCatetoryIdList.get(i));
                    } else if (i == 1) {
                        repairRecord.setVfgId(alarmCatetoryIdList.get(i));
                    } else if (i == 2) {
                        repairRecord.setFaultCategoryId(alarmCatetoryIdList.get(i));
                    }
                }
            }
        }
        // 获取设备故障预防措施列表
        repairRecord.setPreventMeasureList(devFaultPreventMeasureService.queryByRepairTicketId(repairRecord.getId()));
        // 设置下现场照片
        repairRecord.setFaultImages(ticketLiveImageService.getTicketLiveImages("维修前", repairRecord.getId(), "REPAIR"));
        // 设置工单现场图片：进行分组
        List<TicketLiveImageEntity> ticketLiveImages = ticketLiveImageService.queryList(id, "REPAIR");
        if (CollectionUtil.isNotEmpty(ticketLiveImages)) {
            Map<String, List<TicketLiveImageEntity>> temGroup = ticketLiveImages.stream().collect(Collectors.groupingBy(TicketLiveImageEntity::getGroupName));
            Set<Map.Entry<String, List<TicketLiveImageEntity>>> entries = temGroup.entrySet();
            List<TicketLiveImageGroup> ticketLiveImageGroup = CollectionUtil.newArrayList();
            for (Map.Entry<String, List<TicketLiveImageEntity>> entry : entries) {
                ticketLiveImageGroup.add(new TicketLiveImageGroup(entry.getKey(), entry.getValue()));
            }
            repairRecord.setTicketLiveImageGroup(ticketLiveImageGroup);
        }
        return R.ok().put("devMaintenRepair", repairRecord);
    }

    /**
     * 维修工单-完善维修记录
     */
    @LimitSubmit(key = "perfectRepairRecord:%s")
    @RequiresPermissions("devmaintenwork:startOrder")
    @NonBusinessParamValid
    @AutoLog(value = "完善维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequestMapping("/save")
    @ResponseBody
    public R save(@Validated @RequestBody PerfectDevRepairRecordParamVO repairRecordParam, BindingResult bindingResult) {
        // 维修记录ID必填
        String repairRecordId = repairRecordParam.getId();
        if (StrUtil.isEmpty(repairRecordId)) {
            return R.error("维修记录ID必填！");
        }
        // 校验维修记录是否存在
        DevRepairRecordEntity repairRecordInDB = repairRecordService.queryObject(repairRecordId);
        if (repairRecordInDB == null) {
            return R.error("维修记录不存在，请确认！");
        }
        // 如果有报修时间，那么开始维修和结束维修都不得早于报修时间
        Date repairStartDate = repairRecordParam.getRepairStartDate();
        Date repairEndDate = repairRecordParam.getRepairEndDate();
        Date uploadDate = repairRecordInDB.getUploadDate();
        if (uploadDate != null) {
            if (repairStartDate != null && repairStartDate.before(uploadDate)) {
                return R.error("维修开始时间不得早于报修时间！");
            }
            if (repairEndDate != null && repairEndDate.before(uploadDate)) {
                return R.error("维修结束时间不得早于报修时间！");
            }
        }
        // 校验设备是否存在
        DeviceInfoEntity device = deviceService.queryObject(repairRecordParam.getDevId());
        if (device == null) {
            return R.error("设备不存在，请确认！");
        }
        /*
            报警分类CCC一级的ID(faultCategoryId)    设备报警库ID(faultId)
         */
        if (StrUtil.isAllEmpty(repairRecordParam.getFaultCategoryId(), repairRecordParam.getFaultId())) {
            return R.error("CCC分类和设备报警库两者必须指定其中之一！");
        }
        /*
            1、开始维修时间和开始结束时间不得早于当前系统时间
            2、开始维修时间不能晚于结束维修时间
         */
        DateTime current = DateUtil.date();
        if (repairRecordParam.getRepairStartDate().after(current)) {
            return R.error("维修开始时间不得晚于当前系统时间！");
        }
        if (repairRecordParam.getRepairEndDate().after(current)) {
            return R.error("维修结束时间不得晚于当前系统时间！");
        }
        if (repairRecordParam.getRepairStartDate().after(repairRecordParam.getRepairEndDate())) {
            return R.error("维修开始时间不得晚于维修结束时间！");
        }
        // 维修时长必须大于5分钟
        if (DateUtil.between(repairRecordParam.getRepairStartDate(), repairRecordParam.getRepairEndDate(), DateUnit.MINUTE) < 5) {
            return R.error("维修时长不得小于5分钟！");
        }
        // 如果解决办法中出现"更换" 时，换件记录必填
        if (StrUtil.contains(repairRecordParam.getSolution(), "更换")) {
            List<SparePartConsumRecordEntity> consumRecords = sparePartConsumRecordService.queryList("REPAIR", repairRecordParam.getId());
            if (CollectionUtil.isEmpty(consumRecords)) {
                return R.error("请在换件记录内录入更换备件！");
            }
        }
        // 校验如果填写故障预防措施的话，必填校验和日期先后校验
        List<DevFaultPreventMeasure> measureList = repairRecordParam.getPreventMeasureList();
        if (CollectionUtil.isNotEmpty(measureList)) {
            for (DevFaultPreventMeasure measure : measureList) {
                if (!ObjectUtil.isAllNotEmpty(measure.getContent(), measure.getStartDate(), measure.getEndDate())) {
                    return R.error("制定措施时，措施内容、开始时间和结束时间必填！");
                }
                // 开始维修时间不能晚于结束维修时间
                if (measure.getStartDate().after(measure.getEndDate())) {
                    return R.error("预防措施开始时间不得晚于结束时间！");
                }
            }
            repairRecordInDB.setPreventMeasureList(measureList);
        }
        // 校验备件耗用记录中是否有为0的
        List<SparePartConsumRecordEntity> consumRecordList = sparePartConsumRecordService.queryList("REPAIR", repairRecordInDB.getId());
        if (CollectionUtil.isNotEmpty(consumRecordList)) {
            consumRecordList = consumRecordList.stream().filter(consumRecord -> NumberUtil.equals(consumRecord.getNum(), 0)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(consumRecordList)) {
                return R.error("换件记录中使用数量不得等于0！");
            }
        }

        /*
            如果设备报警库ID没填，说明是新增的
                校验下指定设备，特定的报警分类下是否存在这个报警代码
                    如果存在，则直接提示已存在
                    如果不存在，则创建并返回
            如果填写了，需要跟报警代码和
         */
        AlarmCodeBaseEntity alarmCodeBase;
        String faultId = repairRecordParam.getFaultId();
        if (StrUtil.isNotEmpty(faultId)) {
            alarmCodeBase = alarmCodeBaseService.queryObject(faultId);
            if (alarmCodeBase == null) {
                return R.error("当前设备报警代码库不存在，请确认！");
            }
            // 校验是否是这个设备的
            if (!repairRecordParam.getDevId().equals(alarmCodeBase.getDevId())) {
                return R.error("当前设备报警不是这个设备的，请确认！");
            }
            // 验证下报警分类&报警代码的关系
            if (StrUtil.isEmpty(repairRecordParam.getFaultCategoryId())) {
                repairRecordParam.setFaultCategoryId(alarmCodeBase.getAlarmCategoryId());
            } else {
                // 校验是否是这个报警分类下的
                if (!repairRecordParam.getFaultCategoryId().equals(alarmCodeBase.getAlarmCategoryId())) {
                    return R.error("当前设备报警不属于这个报警分类，请确认！");
                }
            }
            repairRecordParam.setFaultCode(alarmCodeBase.getAlarmCode());
            repairRecordParam.setFaultDesc(alarmCodeBase.getAlarmDesc());
        } else {
            // 必填校验
            if (StrUtil.isEmpty(repairRecordParam.getFaultCode())) {
                return R.error("报警代码必填！");
            }
             /*
                理论上：一台设备不管分为多少个部位，报警代码是唯一的
                手动新增时需要区分报警代码已存在和不存在的情形：
                9999：不存在，通用代码
                9999之外的其他情形：
             */
            if (!"9999".equals(repairRecordParam.getFaultCode())) {
                // 获取匹配的设备报警库。如果不存在，则创建
                alarmCodeBase = alarmCodeBaseService.query(null, repairRecordParam.getDevId(), repairRecordParam.getFaultCode());
                if (alarmCodeBase != null) {
                    return R.error("当前设备报警代码[{}]已关联报警分类：[{}]，无需重复录入！", repairRecordParam.getFaultCode(), alarmCodeBase.getTreeName());
                }
            }
            alarmCodeBase = alarmCodeBaseService.queryOrCreateIfNotExists(repairRecordParam.getFaultCategoryId(), repairRecordParam.getDevId(), repairRecordParam.getFaultCode(), repairRecordParam.getFaultDesc(), true);
        }
        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreProperties("measureList", "maintenRecordId");
        // 只允许补充录入的维修记录可以修改开始时间和结束时间
        if (!StrUtil.equals(DeviceTicketSource.SECOND.name(), repairRecordInDB.getSource())) {
            copyOptions.setIgnoreProperties("measureList", "maintenRecordId", "repairStartDate", "repairEndDate");
        }
        BeanUtil.copyProperties(repairRecordParam, repairRecordInDB, copyOptions);
        repairRecordInDB.setFaultId(alarmCodeBase.getId());
        repairRecordInDB.setFaultCategoryId(repairRecordParam.getFaultCategoryId());
        // 设置故障时间
        repairRecordInDB.setFaultDuration(DateUtil.between(repairRecordInDB.getRepairStartDate(), repairRecordInDB.getRepairEndDate(), DateUnit.MINUTE));
        // 如果维修人员为空，那么默认当前完善维修记录的就是维修人员
        if (StrUtil.isEmpty(repairRecordInDB.getRepairUser())) {
            repairRecordInDB.setRepairUser(ShiroUtils.getUserId());
        }
        repairRecordInDB.setWorkshopId(device.getDevFarm());
        return deviceRepairManager.perfectRepairRecord(repairRecordInDB) ? R.ok() : R.error();
    }

    /**
     * 补录维修记录，用于后补维修记录的场景
     */
    @LimitSubmit(key = "doAdditionalRecording:%s")
    @NonBusinessParamValid
    @AutoLog(value = "补录维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequestMapping("/addRepairRecord")
    @RequiresPermissions("devmaintenrepair:save")
    @ResponseBody
    public R addRepairRecord(@Validated @RequestBody PerfectDevRepairRecordParamVO repairRecord, BindingResult bindingResult) {
        // 校验设备是否存在
        DeviceInfoEntity device = deviceService.queryObject(repairRecord.getDevId());
        if (device == null) {
            return R.error("设备不存在，请确认！");
        }
        /*
            报警分类CCC一级的ID(faultCategoryId)    设备报警库ID(faultId)
        */
        if (StrUtil.isAllEmpty(repairRecord.getFaultCategoryId(), repairRecord.getFaultId())) {
            return R.error("CCC分类和设备报警库两者必须指定其中之一！");
        }
        /*
            1、开始维修时间和开始结束时间不得早于当前系统时间
            2、开始维修时间不能晚于结束维修时间
         */
        DateTime current = DateUtil.date();
        if (repairRecord.getRepairStartDate().after(current)) {
            return R.error("维修开始时间不得晚于当前系统时间！");
        }
        if (repairRecord.getRepairEndDate().after(current)) {
            return R.error("维修结束时间不得晚于当前系统时间！");
        }
        if (repairRecord.getRepairStartDate().after(repairRecord.getRepairEndDate())) {
            return R.error("维修开始时间不得晚于维修结束时间！");
        }
        // 维修时长必须大于5分钟
        if (DateUtil.between(repairRecord.getRepairStartDate(), repairRecord.getRepairEndDate(), DateUnit.MINUTE) < 5) {
            return R.error("维修时长不得小于5分钟！");
        }

        /*
            如果设备报警库ID没填，说明是新增的
                校验下指定设备，特定的报警分类下是否存在这个报警代码
                    如果存在，则直接提示已存在
                    如果不存在，则创建并返回
            如果填写了，需要跟报警代码和
         */
        AlarmCodeBaseEntity alarmCodeBase;
        String faultId = repairRecord.getFaultId();
        if (StrUtil.isNotEmpty(faultId)) {
            alarmCodeBase = alarmCodeBaseService.queryObject(faultId);
            if (alarmCodeBase == null) {
                return R.error("当前设备报警代码库不存在，请确认！");
            }
            // 校验是否是这个设备的
            if (!repairRecord.getDevId().equals(alarmCodeBase.getDevId())) {
                return R.error("当前设备报警不是这个设备的，请确认！");
            }
            // 校验是否是这个报警分类下的
            if (StrUtil.isEmpty(repairRecord.getFaultCategoryId())) {
                repairRecord.setFaultCategoryId(alarmCodeBase.getAlarmCategoryId());
            } else {
                // 校验是否是这个报警分类下的
                if (!repairRecord.getFaultCategoryId().equals(alarmCodeBase.getAlarmCategoryId())) {
                    return R.error("当前设备报警不属于这个报警分类，请确认！");
                }
            }
            repairRecord.setFaultCode(alarmCodeBase.getAlarmCode());
            repairRecord.setFaultDesc(alarmCodeBase.getAlarmDesc());
        } else {
            /*
                理论上：一台设备不管分为多少个部位，报警代码是唯一的
                手动新增时需要区分报警代码已存在和不存在的情形：
                9999：不存在，通用代码
                9999之外的其他情形：
             */
            if (!"9999".equals(repairRecord.getFaultCode())) {
                // 获取匹配的设备报警库。如果不存在，则创建
                alarmCodeBase = alarmCodeBaseService.query(null, repairRecord.getDevId(), repairRecord.getFaultCode());
                if (alarmCodeBase != null) {
                    return R.error("当前设备报警代码[{}]已关联报警分类：[{}]，无需重复录入！", repairRecord.getFaultCode(), alarmCodeBase.getTreeName());
                }
            }
            alarmCodeBase = alarmCodeBaseService.queryOrCreateIfNotExists(repairRecord.getFaultCategoryId(), repairRecord.getDevId(), repairRecord.getFaultCode(), repairRecord.getFaultDesc(), true);
        }
        DevRepairRecordEntity devRepairRecord = new DevRepairRecordEntity();
        BeanUtil.copyProperties(repairRecord, devRepairRecord);
        devRepairRecord.setFaultId(alarmCodeBase.getId());
        devRepairRecord.setFaultCategoryId(repairRecord.getFaultCategoryId());
        // 设置故障时间
        devRepairRecord.setFaultDuration(DateUtil.between(devRepairRecord.getRepairStartDate(), devRepairRecord.getRepairEndDate(), DateUnit.MINUTE));
        devRepairRecord.setRepairUser(ShiroUtils.getUserId());
        devRepairRecord.setWorkshopId(device.getDevFarm());
        deviceRepairManager.doAdditionalRecording(devRepairRecord);
        return R.ok().put("repairRecord", devRepairRecord);
    }

    @AutoLog(value = "更新维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequestMapping("/update")
    @RequiresPermissions("devmaintenrepair:update")
    @ResponseBody
    public R update(@RequestBody DevMaintenRepairEntity devMaintenRepair) {
        // 设置故障时间
        devMaintenRepair.setFaultNum(DateUtil.between(devMaintenRepair.getRepairStartDate(), devMaintenRepair.getRepairEndDate(), DateUnit.MINUTE));
        devMaintenRepairService.update(devMaintenRepair);
        return R.ok();
    }

    /**
     * 删除
     */
    @AutoLog(value = "删除维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequestMapping("/delete")
    @RequiresPermissions("devmaintenwork:delete")
    @ResponseBody
    public R delete(@RequestBody String[] ids) {
        repairRecordService.deleteBatch(ids);
        return R.ok();
    }

    /**
     * 查看所有列表
     */
    @RequestMapping("/queryAll")
    @ResponseBody
    public R queryAll(@RequestParam Map<String, Object> params) {

        List<DevMaintenRepairEntity> list = devMaintenRepairService.queryList(params);

        return R.ok().put("list", list);
    }

    /**
     * 导入设备维修记录
     */
    @AutoLog(value = "导入维修记录", busModule = BusModule.DEVICE_REPAIR)
    @RequestMapping("/imports")
    @RequiresPermissions("devmaintenwork:export")
    @ResponseBody
    public R imports(@RequestParam("file") MultipartFile file) throws Exception {
        if (file == null || file.isEmpty()) {
            return R.error("上传文件不能为空！");
        }
        int rows = repairRecordService.importExcelFromStream(file.getInputStream());
        return R.ok("成功导入" + rows + "记录");
    }

}
